package us.codecraft.webmagic.core.downloader.okhttp;

import okhttp3.*;

import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangx <br /> <p>fishlikewater@126.com</p><br />
 * <p> 使用okhttp作为下载客户端</p>
 * @Date 2019年01月24日 12:32
 * @since 0.7.4
 **/
public class OkhttpClientBuild {

    private final HashMap<String, List<Cookie>> cookieStore =new HashMap<>();

    /**
     * 获取okhttp
     * @param config
     * @return
     */
    public OkHttpClient okHttpClient(OkhttpConfig config) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(config.getProxySelector() != null){
            builder.proxySelector(config.getProxySelector());
        }
        if(config.isAutoCookie()){
            builder.cookieJar(new CookieJar() {
                @Override
                public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                    cookieStore.put(url.host(), cookies);
                }

                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    List cookies = cookieStore.get(url.host());
                    return cookies !=null? cookies :new ArrayList();
                }
            });
        }
        OkHttpClient okHttpClient = builder.connectTimeout(config.getConnectionOutTime(), TimeUnit.MILLISECONDS)
                .readTimeout(config.getReadOutTime(), TimeUnit.MILLISECONDS)
                .writeTimeout(config.getWriteTimeout(), TimeUnit.MILLISECONDS)
                .connectionPool(new ConnectionPool(config.getConnectionPool(), config.getKeepAliveDuration(), TimeUnit.MINUTES))
                .retryOnConnectionFailure(config.isRetryOnConnectionFailure())
                .sslSocketFactory(getTrustedSSLSocketFactory(), trustAllCerts)
                .hostnameVerifier(DO_NOT_VERIFY)
                .build();
        okHttpClient.dispatcher().setMaxRequests(config.getMaxRequests());
        okHttpClient.dispatcher().setMaxRequestsPerHost(config.getMaxRequestsPerHost());
        return okHttpClient;
    }

    /**
     * https
     */
    X509TrustManager trustAllCerts = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] x509Certificates = new X509Certificate[0];
                    return x509Certificates;
                }

                public void checkClientTrusted(
                        X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(
                        X509Certificate[] certs, String authType) {
                }
            };

    HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    private SSLSocketFactory getTrustedSSLSocketFactory() {
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, null, new java.security.SecureRandom());
            return sc.getSocketFactory();
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

}
